package com.king.juc.n8.jucdemo.stamped;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.StampedLock;

import static com.king.juc.utils.ThreadUtil.sleep;

/**
 * @author king
 * @date 2020/12/13 14:16
 */
@Slf4j(topic = "c.DataContainerStamped")
public class DataContainerStamped {

    private int data;
    private final StampedLock lock = new StampedLock();

    public DataContainerStamped(int data) {
        this.data = data;
    }

    public int read(int readTime){
        long stamp = lock.tryOptimisticRead();
        log.debug("read lock {}", stamp);
        sleep(readTime);
        if(lock.validate(stamp)){
            log.debug("read finish...{}", stamp);
            return data;
        }

        // 锁升级 - 读锁
        log.debug("updating to read lock... {}", stamp);
        try {
            stamp = lock.readLock();
            log.debug("read lock {}", stamp);
            sleep(readTime);
            log.debug("read finish...{}", stamp);
            return data;
        }finally {
            log.debug("read unlock {}", stamp);
            lock.unlockRead(stamp);
        }
    }

    public void write(int newData){
        long stamp = lock.writeLock();
        log.debug("write lock {}", stamp);
        try {
            sleep(2);
            this.data = newData;
        } finally {
            log.debug("write unlock {}", stamp);
            lock.unlockWrite(stamp);
        }
    }
}
